package cn.kent.high.threadLocalRandom;

import java.util.Random;

/**
 * 多线程下可能会多个线程都拿到同一个老种子去生成随机数，导致生成的新种子都是一样的,进而导致生成的随机数都是一样的。
 * 解决方案： 思路：第一个线程计算出新种子后，第二个线程扔掉老种子，使用第一个线程的新种子，这样多线程下产生的随机数才是随机的。
 *          Random使用了一个原子变量实现了上述效果 在next的源码里面，最后通过CAS操作，使得种子始终最新。
 * 引入问题：多线程下会竞争同一个原子变量的更新操作，而CAS操作导致每次只会有一个线程执行成功，从而导致大量线程进行自旋重试，降低并发性能。
 * 解决方案：使用{@link java.util.concurrent.ThreadLocalRandom}
 *
 *
 * CAS操作解析：
 *     public final boolean compareAndSet(long expect, long update) {
 *         return unsafe.compareAndSwapLong(this, valueOffset, expect, update);
 *     }
 *     四个操作数：对象内存位置、对象中变量的偏移量、变量预期值、新的值
 *     操作含义：如果对象obj中内存偏移量为valueOffset的变量值为expect，则使用新值update替换旧值expect，处理器提供的一个原子性指令。
 */
public class RandomTest {
    public static void main(String[] args) {
        // 创建默认种子的随机数生成器
        Random random = new Random();
        for (int j = 0; j < 10; j++) {
            int i = random.nextInt(10);
            System.out.println(i);
        }

        // public int nextInt(int bound) {
        //     参数检查
        //     if (bound <= 0)
        //         throw new IllegalArgumentException(BadBound);
        //     根据老种子生成新种子
        //     int r = next(31);
        //     int m = bound - 1;
        //     if ((bound & m) == 0)  // i.e., bound is a power of 2
        //         r = (int)((bound * (long)r) >> 31);
        //     else {
        //         for (int u = r;
        //              u - (r = u % bound) + m < 0;
        //              u = next(31))
        //             ;
        //     }
        //     return r;
        // }

        /*
        protected int next(int bits) {
            long oldseed, nextseed;
            AtomicLong seed = this.seed;
            do {
                // 获取当前原子变量种子的值
                oldseed = seed.get();
                // 根据当前种子值计算新种子
                nextseed = (oldseed * multiplier + addend) & mask;
                // 使用CAS操作，使用新种子更新老种子 --> 保证了只有一个线程可以更新老的种子为新的
            } while (!seed.compareAndSet(oldseed, nextseed));
            return (int)(nextseed >>> (48 - bits));
        }
        */
    }
}
